package com.bantang;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.lang.UUID;
import com.bantang.model.JudgeInfo;
import com.bantang.model.SandBoxParam;
import com.bantang.model.SandBoxVO;
import com.bantang.utils.CompileCodeUtil;
import com.bantang.utils.ExecResult;


import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class JavaNativeCodeSandbox implements CodeSandBox {

    //测试工具类
    public static void main(String[] args) {

        CodeSandBox codeSandBox = new JavaNativeCodeSandbox();
        SandBoxParam sandBoxParam = new SandBoxParam();
        sandBoxParam.setLanguage("java");

        String code = ResourceUtil.readStr("testCode/Main.java", StandardCharsets.UTF_8);

        sandBoxParam.setCode(code);
        sandBoxParam.setInput(Arrays.asList("1 2", "3 4"));

        SandBoxVO sandBoxVO = codeSandBox.executeCodeSandBox(sandBoxParam);

        System.out.println(sandBoxVO);
    }

    /**
     * Java原生实现 代码沙箱
     *
     * @param sandBoxParam
     * @return
     */
    @Override
    public SandBoxVO executeCodeSandBox(SandBoxParam sandBoxParam) {
        SandBoxVO sandBoxVO = new SandBoxVO();

        //获取代码 输入用例
        String code = sandBoxParam.getCode();
        List<String> input = sandBoxParam.getInput();

        //获取项目根路径
        String userDir = System.getProperty("user.dir");
        //在根目录创建文件夹
        String codePathName = userDir + File.separator + "tempCode";
        if (!FileUtil.exist(codePathName)) {
            FileUtil.mkdir("tempCode");
        }
        //把用户代码隔离 写入新的文件夹 Main.java
        String userCodePath = codePathName + File.separator + UUID.randomUUID();
        String userCodePathName = userCodePath + File.separator + "Solve.java";
        File userFile = FileUtil.writeString(code, userCodePathName, StandardCharsets.UTF_8);

        //编译代码 生成Main.class
        String codeCmd = String.format("javac -encoding utf-8 %s", userFile.getAbsolutePath());
        ExecResult execResult = CompileCodeUtil.compileCode(codeCmd);

        //1)编译错误
        if (!"success".equals(execResult.getMessage())) {
            sandBoxVO.setBoxMessage("编译错误");
            return sandBoxVO;
        }

        //运行代码
        List<String> outputValues = new ArrayList<>();
        JudgeInfo judgeInfo = new JudgeInfo();

        Long maxTime = 0L;
        for (String s : input) {

            String codeCmdRun = String.format("java -Xmx256m -cp %s Solve %s", userCodePath, s);
            ExecResult runResult = CompileCodeUtil.compileCode(codeCmdRun);

            String message = runResult.getMessage();
            String result = runResult.getOutput();
            Long time = runResult.getTime();
            if (time > maxTime) {
                maxTime = time;
            }
            //2) 运行错误
            if (!"success".equals(execResult.getMessage())) {
                sandBoxVO.setBoxMessage("运行失败");
                judgeInfo.setMessage(message);
                judgeInfo.setTime(maxTime);
                sandBoxVO.setJudgeInfo(judgeInfo);
                return sandBoxVO;
            }
            outputValues.add(result);
        }

        //3) 运行成功
        sandBoxVO.setBoxMessage("运行成功");
        sandBoxVO.setOutput(outputValues);
        judgeInfo.setTime(maxTime);
        judgeInfo.setMessage("success");
        sandBoxVO.setJudgeInfo(judgeInfo);

        //删除编译路径
        FileUtil.del(userCodePath);
        return sandBoxVO;
    }

}
